", 7)) return buf;
else if (!StrNICmp( cp, "", 3)) return buf; // ?? weak test but need
else if (!StrNICmp( cp, "", 3, false, &at)) return true;
// }
cp++;
len -= (cp - atbuf);
atbuf = cp;
}
else
return NULL;
}
return NULL;
}
DHTMLHandler::DHTMLHandler( DRichView* itsDoc, DFile* savefile) :
DRichHandler( itsDoc, savefile)
{
fFormatName = "HTML";
fMinDataToProcess= 128; // no fixed min, need to look at data...
if (!gHTMLsetup) gHTMLsetup= new DHTMLsetup();
}
DHTMLHandler::~DHTMLHandler()
{
}
DRichprocess* DHTMLHandler::NewProcessor( DFile* itsFile, Nlm_MonitorPtr progress)
{
fProcessor = new DHTMLprocess( itsFile, fDoc, progress);
return fProcessor;
}
Boolean DHTMLHandler::ProcessData( char* cbeg, char* cend, Boolean endOfData,
ulong& dataRemaining)
{
char * cp;
fcsave= 0;
fclen= cend - cbeg; // + 1;
cp= cend;
if (!endOfData) {
if ((fclen==0) || ( fProcessStage == kAtStart && fclen fLastScanto && !(*cp == '\n' || *cp == '\r')) cp--;
if (cp < cend && (*cp == '\n' || *cp == '\r')) cp++;
#endif
}
#if 1 //TEST w/out << NEED THIS for at least some
if (cp - cbeg <= fLastScanto) {
fLastScanto= cend - cbeg;
if (!endOfData) return false; // !??! don't process line w/o end
else cp= cend;
}
#endif
#if 0 // bad nulls ??
if (*cp) cp++;
fcsave= *cp;
*cp= 0;
#endif
fclen= cp - cbeg; // + 1;
if (fclen && fDocFile) {
if (cbeg[fclen-1] == 0) fclen--; //??
fDocFile->WriteData( cbeg, fclen);
}
return this->ProcessData2( cp, cbeg, cend, endOfData, dataRemaining);
}
// class DHTMLprocess
//static char gGenCharMap[rtfSC_MaxChar];
//static char * gOutMap = gGenCharMap;
DHTMLprocess::DHTMLprocess( DFile* itsFile, DRichView* itsDoc, Nlm_MonitorPtr progress) :
DRichprocess( itsFile, itsDoc, progress),
fStop(0), fTokenLen(0), fListType(0), fListNum(0), fDLStyle(0), fQuote(0),
fCurControl(0), fCurField(0), fLastField(0), fPicLink(0), fAnchorLink(0),
fURLstore(NULL), fNamestore(NULL), fFormURL(NULL), fGoplusStore(NULL),
fMethodstore(NULL), fValstore(NULL), fTypestore(NULL), fOptionstore(NULL),
fSizestore(NULL),fMaxlengthstore(NULL),fRowsstore(NULL),fColsstore(NULL),
fPushSize(0), fPushBuf(NULL), fPushBufstore(NULL),
fInHead(true), fInParam(false), fInForm(false), fInControl(false), fIsMap(false),
fIsChecked(false), fSelectitem(0), fCurItem(0), fIsMultiple(false),
fTurnOn(true), fIsIndex(false), fPreformat(false)
{
//fOutMap= DRichprocess::gGenCharMap;
}
DHTMLprocess::~DHTMLprocess()
{
MemFree(fURLstore);
MemFree(fNamestore);
MemFree(fMethodstore);
MemFree(fGoplusStore);
MemFree(fFormURL);
MemFree(fValstore);
MemFree(fTypestore);
MemFree(fOptionstore);
MemFree(fPushBufstore);
MemFree(fSizestore);
MemFree(fMaxlengthstore);
MemFree(fRowsstore);
MemFree(fColsstore);
}
//static
short DHTMLprocess::Hash( char *s)
{
char c;
short val = 0;
while ((c = *s++) != '\0') val += (int) tolower(c);
return (val);
}
//static
void DHTMLprocess::InitKeys()
{
HTMLKey *rp;
for (rp = htmlKeys; rp->htmlKStr != NULL; rp++) {
rp->htmlKHash = Hash(rp->htmlKStr);
}
for (rp = htmlAmperChars; rp->htmlKStr != NULL; rp++) {
rp->htmlKHash = Hash(rp->htmlKStr);
}
}
void DHTMLprocess::Lookup( char *s, HTMLKey* keyset)
{
HTMLKey *rp;
short hash;
#ifdef COMP_BOR /* ?? dgg */
int LIBCALL (*cmp)(const char*,const char*);
#else
#ifdef COMP_SYMC
int (* LIBCALL cmp)(const char*, const char*);
#else
int (*cmp)(const char*,const char*);
#endif
#endif
if (keyset == htmlAmperChars) cmp= Nlm_StringCmp;
else cmp= Nlm_StringICmp;
fClass = tokUnknown;
if (*s == 0) return;
hash = Hash(s);
for (rp = keyset; rp->htmlKStr != NULL; rp++) {
if (hash == rp->htmlKHash && cmp(s, rp->htmlKStr) == 0) {
fClass = tokControl;
fMajor = rp->htmlKMajor;
fMinor = rp->htmlKMinor;
fStop = rp->htmlKStop;
return;
}
}
}
void DHTMLprocess::Pushback(char c) // private
{
if (c != EOF) {
fPushedChar = c;
}
}
enum {
kGotNone = 0,
kGotToken,
kGotParam
};
short DHTMLprocess::GotTokenOrParam() // private
{
if (fTokenLen>0) { // need to process last token !
fTokenBuf[fTokenLen] = '\0';
long i, tokenlen= fTokenLen;
fTokenLen= 0;
if (fInParam) {
switch (fCurField) {
case htmlIsMap:
fIsMap= true;
break;
case htmlAction:
case htmlImageSrc:
case htmlHref:
for (i=0; i':
{
if (fInControl && fQuote) goto cInQuote;
if (!fInControl) goto cHandleText;
if (GotTokenOrParam() != kGotNone) {
Pushback(c);
return;
}
if (fCurField == htmlOption) { // fCurControl == htmlSelect &&
Pushback('='); // turn following text into option Param...
return;
}
fInControl= false;
fClass = tokControl;
fMajor = htmlEndControl;
fMinor = -1;
return;
}
case '<':
if (fInControl && fQuote) goto cInQuote;
if (fQuote == (char)234) { // kInFormText
fInControl= false;
this->handleLinkAttr( fCurControl);
}
fInControl= true;
fTurnOn= true;
fInParam= false;
fQuote= 0;
fCurControl= 0;
fCurField= 0;
fTokenLen= 0;
fPicLink= 0;
//fAnchorLink= 0;
fClass = tokDropchar;
return;
default:
if (fInControl) {
cInQuote:
// !! need to deal with complex options in syntax
// e.g. text here
// e.g. < IMG SRC ="triangle.gif" ALT="Warning:"> text here...
// < A HREF="Go">< IMG SRC ="Button"> Press to start
if ( (fQuote && c != fQuote)
|| (fInParam && c != fQuote && c != '"' && c != '\'' && c > ' ')
|| isalnum(c) ) {
// store in token buf until unquoted
if (fTokenLen EOF && isalnum(c));
fTokenBuf[fTokenLen] = '\0';
Lookup( fTokenBuf, htmlAmperChars); // sets class, major, minor
return;
case '\t':
fClass = tokControl;
fMajor = htmlSpecialChar;
fMinor = htmlTab;
return;
case '\r':
case '\n': //NEWLINE:
if (fPreformat) {
fClass = tokControl;
fMajor = htmlSpecialChar;
fMinor = htmlNewline;
}
else if (fTextSize>0) {
// messy fix for that cutesy horizontal bar
if ( fTextSize > 15 && fText[15] == '_'
&& fText[1] == '_' && fText[fTextSize-2] == '_') {
fTextSize= 0;
handleSpecialChar( htmlHBar);
fClass = tokDropchar;
}
else
// put space in, if this isn't new parag
goto cHandleSpace;
}
else
fClass = tokDropchar;
return;
case ' ':
cHandleSpace:
if (fPreformat || fLastChar != ' ') {
fClass = tokText;
fMajor = ' ';
fMinor = ' '; // MapChar( c);
}
else
fClass = tokDropchar;
return;
case '\0':
fClass = tokDropchar;
return;
default:
cHandleText:
fClass = tokText;
fMajor = c;
fMinor = c; // MapChar( c);
return;
}
}
}
}
short DHTMLprocess::GetOneChar()
{
#if 1
if (fPushSize && fPushBuf) {
short c= (unsigned char) *fPushBuf; // must be unsigned !!
fPushSize--;
fPushBuf++;
return c;
}
else
return DRichprocess::GetOneChar();
#else
short c;
if (fDataBuffer) {
c= (unsigned char) *fDataBuffer; // must be unsigned !!
if (fDataSize) { // for counted data
fDataSize--;
fDataBuffer++;
if (!fDataSize) fDataBuffer= NULL; // so EOF next time
}
else if (c) fDataBuffer++; // for null-term data
else if (!fEndOfData) c= tokBreakInData;
else c= EOF;
}
else if (fDataFile)
c = fgetc( fDataFile->fFile);
else {
if (!fEndOfData) c= tokBreakInData;
else c= EOF;
}
return (c);
#endif
}
void DHTMLprocess::handleTextClass()
{
if (IsNewStyle()) StoreStyle(fOldStyleRec.style, FALSE);
if (fMinor != rtfSC_nothing)
PutStdChar(fMinor);
else {
char buf[128];
if (fMajor < 128) /* in ASCII range */
sprintf (buf, "[[%c]]", fMajor);
else
sprintf (buf, "[[\\'%02x]]", fMajor);
PutLitStr (buf);
}
fLastChar= fMajor;
}
void DHTMLprocess::handleControlClass()
{
switch (fMajor) {
case htmlDocAttr : handleDocAttr(fMinor); break;
case htmlLinkAttr : handleLinkAttr(fMinor); break;
case htmlFormAttr : handleFormAttr(fMinor); break;
case htmlCharAttr : handleCharAttr(fMinor); break;
case htmlParAttr : handleParAttr(fMinor); break;
case htmlListAttr : handleListAttr(fMinor); break;
case htmlPictAttr : handlePictAttr(fMinor); break;
case htmlSpecialChar: handleSpecialChar(fMinor); break;
case htmlEndControl: handleEndControl(fMinor); break;
}
}
void DHTMLprocess::handleEndControl(short attr)
{
// e.g, > end of any control
if (fCurControl == htmlForm
|| fCurControl == htmlInput
//|| fCurControl == htmlSelect
//|| fCurControl == htmlTextarea
) {
// call here AFTER DNetHTMLprocess::handleEndControl
this->handleFormAttr( fCurControl); //?? !? why this mess here
}
else if (fCurControl == htmlImage) {
short kind;
char * dummypict = (char*) MemNew( 1);
*dummypict= 0;
if (fAnchorLink) kind= DPictStyle::kPictNetLink;
else kind= DPictStyle::kPictNetPic;
DPictStyle* thePic= new DPictStyle( kind, dummypict, 1, true);
if (!fParaCount) NewParagraph();
if (fPicLink) {
Nlm_RecT loc;
Nlm_LoadRect( &loc, 0, 0, 35, 22); // top is to fetch picture
thePic->AddLink( DPictStyle::kPictNetPic, fPicLink, loc);
if (fAnchorLink) {
Nlm_LoadRect( &loc, 0, 23, 35, 35); // bottom is to fetch link info
thePic->AddLink( DPictStyle::kPictNetLink, fAnchorLink, loc);
}
fPicLink= 0;
}
// !? in html, is damn url suffix supposed indicate TYPE of data !?
// or can we assume all these are GIF pictures ?
fStyleRec.style.ismap= fIsMap;
StoreStyleObject( thePic, 35, 35);
}
fCurControl= 0;
fCurField= 0;
fIsMap= false;
}
void DHTMLprocess::handleDocAttr(short attr)
{
switch (attr) {
case htmlHTML:
if (fTurnOn) fCurControl= attr;
break;
case htmlHead: fInHead= fTurnOn; break;
case htmlBody: fInHead= false; break;
case htmlTitle:
// ! this htmlTitle can occur both in Head and Body/Anchor
if (fTurnOn) {
fCurControl= attr; //??
fNamestore= (char*) MemFree(fNamestore);
}
else {
#if 0
fTitle= fNamestore;
fNamestore= NULL;
#else
if (fTextSize) { // fInHead &&
MemFree(fTitle);
fText[fTextSize]= '\0';
fTitle= StrDup( fText);
fTextSize= 0;
}
#endif
}
break;
case htmlIsIndex: {
fIsIndex= true;
MemFree(fPushBufstore);
fPushBufstore= StrDup(" Click here to query ");
fPushBuf= fPushBufstore;
fPushSize= StrLen(fPushBuf);
//MemFree(fURLstore);
//fURLstore= StrDup("#");
// entire doc is somehow flagged as a query document, and need
// some kind of button to send query to server from this doc !?
// go->fType= kTypeQuery;
}
break;
case htmlBase:
break;
case htmlLink:
case htmlNextID:
break;
//case htmlHref: // !! bug in processing tokens -- arrive here after finding Link/HREF !
}
}
#if 0
/////////// html forms stuff ///////////////
///// convert to gopher ask forms ///////////
// forms tags
htmlLinkAttr, htmlForm, "form", kSlashStop, 0,
htmlLinkAttr, htmlInput, "input", kNoStop, 0,
htmlLinkAttr, htmlSelect, "select", kSlashStop, 0,
htmlLinkAttr, htmlTextarea, "textarea", kSlashStop, 0,
htmlLinkAttr, htmlValue, "value", kNoStop, 0,
htmlLinkAttr, htmlType, "type", kNoStop, 0,
htmlLinkAttr, htmlOption, "option", kNoStop, 0,
htmlLinkAttr, htmlAction, "action", kNoStop, 0,
htmlLinkAttr, htmlMethod, "method", kNoStop, 0,
#endif
void DHTMLprocess::handleFormAttr(short attr)
{
char buf[512];
DWindow* fWin;
DControlStyle* cs;
switch (attr) {
case htmlForm:
fCurControl= attr;
fCurField= attr;
fInForm= fTurnOn;
if (fInForm) {
if (fInControl) {
fURLstore= (char*) MemFree(fURLstore);
fMethodstore= (char*) MemFree(fMethodstore);
fFormURL= (char*) MemFree(fFormURL);
//fGoplusStore= (char*) MemFree(fGoplusStore);
//fGoplusStore= StrDup("+ASKHTML:\n");
PushStyle();
fIsChecked= fIsMultiple= false; fSelectitem= 0;
}
else {
//